using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Http;
using System.Web.Script.Serialization;
using Nop.Core;
using Nop.Core.Data;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using Nop.Core.Log;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Configuration;
using Nop.Services.Customers;
using Nop.Services.Logging;
using Nop.Services.Messages;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Services.Stores;
using Spotshub.Api.Filter;

namespace Spotshub.Api.Controllers.V1
{
    [ExceptionHandler]
    public class PaymentController : ApiController
    {
        private readonly IWorkContext _workContext;
        private readonly ICustomerService _customerService;
        private readonly ISettingService _settingService;
        private readonly IStoreService _storeService;
        private readonly IOrderProcessingService _orderProcessingService;
        private readonly IOrderService _orderService;
        private readonly IPaymentService _paymentService;
        private readonly IRepository<Order> _ordeRepository;
        private readonly IProductService _productService;
        private readonly IWorkflowMessageService _workflowMessageService;
        private readonly ILogger _logger;
        private readonly PaymentSettings _paymentSettings;
        //private readonly IGlobalPaymentsService _globalPaymentsService;
        private const int storeId = 31;
        public PaymentController(
            IWorkContext workContext,
            ICustomerService customerService,
            ISettingService settingService,
            IStoreService storeService,
            IOrderProcessingService orderProcessingService,
            IOrderService orderService,
            IPaymentService paymentService,
            IRepository<Order> ordeRepository,
            IProductService productService,
            IWorkflowMessageService workflowMessageService,
            ILogger logger,
            PaymentSettings paymentSettings
            )
        {
            this._workContext = workContext;
            this._customerService = customerService;
            this._settingService = settingService;
            this._storeService = storeService;
            this._orderProcessingService = orderProcessingService;
            this._orderService = orderService;
            this._paymentService = paymentService;
            this._ordeRepository = ordeRepository;
            this._productService = productService;
            this._workflowMessageService = workflowMessageService;
            this._logger = logger;
            this._paymentSettings = paymentSettings;
        }

        //public int GetUserId(int userId)
        //{
        //    if (String.IsNullOrEmpty(userId.ToString()))
        //    {
        //        return 0;
        //    }
        //    return userId;
        //}

        /// <summary>
        /// 对象转换为json方式
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private string ObjectToJson(object obj)
        {
            string str = obj.ToString();
            return str;
            //string str;
            //if (obj is string || obj is char)
            //{
            //    str = obj.ToString();
            //}
            //else
            //{
            //    var serializer = new JavaScriptSerializer();
            //    str = serializer.Serialize(obj);
            //}
            //var result = new HttpResponseMessage { Content = new StringContent(str, Encoding.GetEncoding("UTF-8"), "application/json") };
            //return result;
        }

        /// <summary>
        /// 获取支付链接
        /// </summary>
        /// <param name="orderId">运单ID</param>
        /// <param name="name">名字</param>
        /// <param name="amount">金额</param>
        /// <returns></returns>
        [HttpGet]
        public object GetPaymentUrl(string name, decimal amount, int orderId)
        {
            //var checkOrder=_orderService.GetOrdersByCustomerId(_workContext.CurrentCustomer.Id, orderId: orderId).FirstOrDefault();

            //return RePaymentUrl(name, amount, orderId);
            CheckCustomerLogin();
            IPaymentMethod paymentMethod = null;
            paymentMethod = _paymentService.LoadPaymentMethodBySystemName("Payments.GlobalPayments");
            var customerId = _workContext.CurrentCustomer.Id;
            var formUrl = paymentMethod.GetSecureFormUrl(customerId, storeId, "app");
            var url = "";
            if (formUrl != null)
            {
                url = formUrl.Url;
            }
            return new { url = url };
        }

        public object GetPaymentUrl(decimal amount, int orderId)
        {
            return RePaymentUrl("", amount, orderId);
        }
        [HttpGet]
        public object GetPaymentUrl()
        {
            CheckCustomerLogin();
            IPaymentMethod paymentMethod = null;
            paymentMethod = _paymentService.LoadPaymentMethodBySystemName("Payments.GlobalPayments");
            var customerId = _workContext.CurrentCustomer.Id;
            var formUrl = paymentMethod.GetSecureFormUrl(customerId, storeId, "app");
            var url = "";
            if (formUrl != null)
            {
                //url = formUrl.Url;
                url = _settingService.GetSettingByKey("apipaymentssettings.ifarmeUrl").Value;
                url = string.Format(url, "uid=" + formUrl.Uid);
            }
            return new { url = url };
        }

        [HttpGet]
        public List<Models.PaymentCreditCard> GetUserPaymentsCreditCards()
        {
            CheckCustomerLogin();

            var creditCardCardList = new List<Models.PaymentCreditCard>();

            IPaymentMethod paymentMethod = null;

            paymentMethod = _paymentService.LoadPaymentMethodBySystemName("Payments.GlobalPayments");
            var creditCards = paymentMethod.GetCreditCards();
            if (creditCards != null)
            {
                foreach (var creditCard in creditCards)
                {
                    var paymentcreditCard = new Models.PaymentCreditCard
                    {
                        Id = creditCard.Id,
                        ExpiryMonth = creditCard.CreditCardExpireMonth,
                        ExpiryYear = creditCard.CreditCardExpireYear,
                        Name = creditCard.CreditCardName,
                        Number = creditCard.CreditCardNumber
                    };
                    creditCardCardList.Add(paymentcreditCard);
                }
            }
            return creditCardCardList;
        }

        [HttpGet]
        public Models.PaymentCreditCard GetUserPaymentsCreditCard(int id = 0)
        {
            CheckCustomerLogin();
            var creditcard = new Models.PaymentCreditCard();
            var customerId = _workContext.CurrentCustomer.Id;
            IPaymentMethod paymentMethod = null;

            paymentMethod = _paymentService.LoadPaymentMethodBySystemName("Payments.GlobalPayments");

            if (id == 0)
            {
                var creditCarLast = paymentMethod.GetCreditCardByLast(customerId, storeId);
                if (creditCarLast != null)
                {
                    creditcard.Id = creditCarLast.Id;
                    creditcard.ExpiryMonth = creditCarLast.CreditCardExpireMonth;
                    creditcard.ExpiryYear = creditCarLast.CreditCardExpireYear;
                    creditcard.Name = creditCarLast.CreditCardName;
                    creditcard.Number = creditCarLast.CreditCardNumber;
                    return creditcard;
                }
            }
            else
            {
                var creditCard = paymentMethod.GetCreditCardById(id);
                if (creditCard != null)
                {
                    creditcard.Id = creditCard.Id;
                    creditcard.ExpiryMonth = creditCard.CreditCardExpireMonth;
                    creditcard.ExpiryYear = creditCard.CreditCardExpireYear;
                    creditcard.Name = creditCard.CreditCardName;
                    creditcard.Number = creditCard.CreditCardNumber;
                    return creditcard;
                }
            }
            return null;
        }
        [HttpPost]
        public object CreateCardPay([FromBody] Models.CreditCardPay creditCardPay)
        {
            CheckCustomerLogin();
            if (creditCardPay != null && creditCardPay.Id > 0 && creditCardPay.OrderId > 0)
            {
                var order = _orderService.GetOrderById(creditCardPay.OrderId);
                if (order == null)
                    return new { success = false, errorMessage = "this order is null." };
                if (order.PaymentStatus == Nop.Core.Domain.Payments.PaymentStatus.Paid)
                    return new { success = false, errorMessage = "this order is pid." };

                IPaymentMethod paymentMethod = null;
                paymentMethod = _paymentService.LoadPaymentMethodBySystemName("Payments.GlobalPayments");

                var pay = paymentMethod.CreditCardPay(creditCardPay.Id, creditCardPay.OrderId);
                if (pay.Success)
                {
                    UpdatePaySuccessOrder(order);
                    return new { success = true };
                }
                return new { success = false, errorMessage = string.Join(";", pay.Errors.ToArray()) };
            }
            return new { success = false, errorMessage = "Please check your parameter" };
        }

        private void UpdatePaySuccessOrder(Order order)
        {
            order.PaymentStatus = PaymentStatus.Paid;
            order.PaymentMethodSystemName = "Payments.GlobalPayments";
            _ordeRepository.Update(order);

            //发送邮件
            int orderPlacedCustomerNotificationQueuedEmailId = _workflowMessageService.SendOrderPlacedCustomerNotification(order, order.CustomerLanguageId);
            if (orderPlacedCustomerNotificationQueuedEmailId > 0)
            {
                order.OrderNotes.Add(new OrderNote()
                {
                    Note = string.Format("\"Order placed\" email (to customer) has been queued. Queued email identifier: {0}.", orderPlacedCustomerNotificationQueuedEmailId),
                    DisplayToCustomer = false,
                    CreatedOnUtc = DateTime.UtcNow
                });
                _orderService.UpdateOrder(order);
            }
            //修改库存
            foreach (var productVarant in order.OrderProductVariants)
            {
                if (productVarant != null && productVarant.Quantity > 0 && productVarant.ProductVariant != null && productVarant.ProductVariant.StockQuantity > 0)
                {
                    _productService.AdjustInventory(productVarant.ProductVariant, true, productVarant.Quantity, productVarant.AttributesXml);
                }
            }


        }
        private object RePaymentUrl(string name, decimal amount, int orderId)
        {
            var checkOrder = _orderService.GetOrdersByCustomerId(_workContext.CurrentCustomer.Id, orderId: orderId).FirstOrDefault();
            if (checkOrder == null)
            {
                return "The order does not exist.";
            }
            var customerId = _workContext.CurrentCustomer.Id;

            if (string.IsNullOrEmpty(name))
            {
                name = "";
            }
            var uId = GetUID(customerId, storeId, name, amount, orderId);
            var url = _settingService.GetSettingByKey("apipaymentssettings.ifarmeUrl").Value;
            url = string.Format(url, uId);
            var obj = new { url = url };
            return obj;
        }
        private string CheckPaymentMessage()
        {
            var message = "success";

            var customerId = _workContext.CurrentCustomer.Id;
            var customer = _customerService.GetCustomerById(customerId);
            var cart = customer.ShoppingCartItems.Where(x => x.ShoppingCartTypeId == 1).ToList();

            if (customerId == 0)
            {
                message = "Please submit after landing";
                return message;
            }
            if (cart.Count == 0)
            {
                message = "Your shopping cart is empty";
                return message;
            }
            return message;
        }

        protected string GetUID(int customerId, int storeId, string name, decimal amount, int orderId)
        {
            //var merchPass = "gt694878820888SB";
            var merchPass = _settingService.GetSettingByKey("apipaymentssettings.merchPass").Value;
            var cssUrl = _settingService.GetSettingByKey("globalpaymentssettings.appcssurl").Value;
            Random rd = new Random();
            int sessId = rd.Next(100000, 1000000);

            var uidUrl = _settingService.GetSettingByKey("apipaymentssettings.merchPass_GetUID_Url").Value;

            uidUrl = uidUrl + "?action=buildForm&merchPass={0}&allowed_types=Visa|MasterCard|American Express|Discover|GSA SmartPay&formType=5&lang=en_US&name={1}&amount={2}&customer_id={3}&currency_code=CAD&sessionId={4}&orderId={5}&css_url={6}";

            var getUidUrl = uidUrl;
            if (!string.IsNullOrEmpty(name))
            {
                getUidUrl = string.Format(getUidUrl, merchPass, name, amount, customerId, sessId, orderId, cssUrl);
            }
            else
            {
                getUidUrl = string.Format(getUidUrl, merchPass, "", amount, customerId, sessId, orderId, cssUrl);
            }
            var getUid = PostDirectService(getUidUrl);
            return getUid;
        }
        public string PostDirectService(string url)
        {
            string res = null;
            try
            {
                using (WebClient wc = new WebClient())
                {
                    res = wc.UploadString(url, "POST", "");
                }
            }
            catch (Exception exc)
            {
                throw new NopException("Failed to post direct service. Url: {0} Exception: {1}", url, exc);
            }

            return res;
        }

        private void CheckCustomerLogin()
        {
            if (_workContext.CurrentCustomer.IsGuest())
                throw new Exception("Anonymous checkout is not allowed");
        }
    }
}
